import {Conflux, format, Drip} from "js-conflux-sdk"
import Web3 from 'web3'
import poolAbi from '@/contract/CfxPosPoolAbi.json'

// abc pool地址
const poolContractMainnetAddr = 'cfx:accpx9uxky39pg1hzav757vdej95w1kbcp13d0hvm7'
const poolContractTestnetAddr = 'cfxtest:acacf3g9z6rav9ep5r3ez38ehsdvusa6xu6k4n88na'
const espaceTestChainId = 71
const espaceMainChainId = 1030
const cspaceTestChainId = 1
const cspaceMainChainId = 1029
const testnet = 'testnet'
const mainnet = 'mainnet'
const cspace = 'cspace'
const espace = 'espace'
const unknown = 'unknown'
const walletFluent = 'Fluent'
const walletOneKey = 'OneKey'

export default {
    wallet: '',
    space: '',
    network: '',
    coreClient: null,
    espaceClient: null,
    poolContractInst: null,
    //oneKey初始化
    isCoreSpace() {
        return this.space === cspace
    },
    async oneKeyInit(callback) {

        let cspaceProvider = null
        let espaceProvider = null

        if (window.conflux) {
            if (window.conflux.isFluent) {
                this.wallet = walletFluent
                cspaceProvider = window.conflux
                espaceProvider = window.ethereum
            }
        }

        if (window.$onekey) {
            this.wallet = walletOneKey
            cspaceProvider = window.$onekey.conflux
            espaceProvider = window.$onekey.ethereum
        }

        if (null === cspaceProvider) {
            return null
        }

        this.coreClient = new Conflux({
            networkId: 1,
        });

        this.coreClient.provider = cspaceProvider;
        this.registeEventListener(cspaceProvider, callback)
        this.espaceClient = new Web3(espaceProvider)
        this.registeEventListener(espaceProvider, callback)

        await this.getSpaceNetwork()

        let result = {}

        if (this.space === cspace) {
            let addr = ''
            if (this.network === mainnet) {
                addr = poolContractMainnetAddr
            } else if (this.network === testnet) {
                addr = poolContractTestnetAddr
            }
            this.poolContractInst = this.coreClient.Contract({abi: poolAbi.abi, address: addr})
            result.poolAddr = this.poolContractInst.address
        }

        result.wallet = this.wallet
        result.space = this.space
        result.network = this.network

        return result
    },
    //返回core网络信息
    async getSpaceNetwork() {

        try {
            this.network = unknown
            const coreSpace = await this.coreClient.cfx.getStatus()
            if (coreSpace) {
                this.space = cspace
                if (coreSpace.chainId === cspaceTestChainId) {
                    this.network = testnet
                }
                if (coreSpace.chainId === cspaceMainChainId) {
                    this.network = mainnet
                }
                // 更新core客户端的网络id
                this.coreClient.networkId = coreSpace.chainId
            }
        } catch (e) {

            const espaceChainId = await this.espaceClient.eth.getChainId()
            this.space = espace
            if (espaceChainId === espaceTestChainId) {
                this.network = testnet
            }
            if (espaceChainId === espaceMainChainId) {
                this.network = mainnet
            }
        }
    },
    registeEventListener(provider, callback) {
        if (null === provider) {
            return
        }
        provider.on('chainChanged', chainId => {
            console.log('chainChanged', chainId)
            if (callback && callback['chainChanged']) {
                callback['chainChanged'](chainId)
            }
        })
        provider.on('accountsChanged', (accounts) => {
            console.log('accountsChanged', accounts)
            if (callback && callback['accountsChanged']) {
                callback['accountsChanged']()
            }
        })
        provider.on('connect', (res) => {
            console.log('connect', res)
            if (callback && callback['connect']) {
                callback['connect']()
            }
        })
        provider.on('disconnect', () => {
            console.log('disconnect')
            if (callback && callback['disconnect']) {
                callback['disconnect']()
            }
        })
    },
    getProvider() {
        if (this.space === cspace) {
            return this.coreClient.provider
        }
        if (this.space === espace) {
            return this.espaceClient.givenProvider
        }
        return null
    },
    selectedAddress() {
        return this.getProvider().request({method: this.formatRequestMethod('eth_accounts')})
    },
    formatRequestMethod(method) {
        if (this.wallet === walletFluent) {
            if (this.space === cspace) {
                return method.replaceAll('eth', 'cfx')
            }
        }
        return method
    },
    //获取网络版本
       netVersion() {
        return window.conflux.request({ method: 'net_version' })
    },
    async getAccount() {
        let account = ''
        const accounts = await this.getProvider().request({method: this.formatRequestMethod('eth_requestAccounts')});
        if (accounts.length > 0) {
            account = accounts[0]
        }
        return account
    },
    getBalance(from) {
        return new Promise(resolve => {
            if (this.space === cspace) {
                this.coreClient.cfx.getBalance(from).then(res => {
                    resolve(Drip(res).toCFX())
                })
            } else if (this.space === espace) {
                this.espaceClient.eth.getBalance(from).then(res => {
                    resolve(Web3.utils.fromWei(res))
                })
            }
        })
    },
    getPoolName() {
        return this.poolContractInst.poolName().call()
    },
    getPoolApy() {
        return new Promise(resolve => {
            this.poolContractInst.poolAPY().call().then(res => {
                resolve(res.toString())
            })
        })
    },
    getPoolStakerNumber() {
        return new Promise(resolve => {
            this.poolContractInst.stakerNumber().call().then(res => {
                resolve(res.toString())
            })
        })
    },
    getPoolPosAddress() {
        return new Promise(resolve => {
            this.poolContractInst.posAddress().call().then(res => {
                resolve(format.hex(res))
            })
        })
    },
    getPoolSummary() {
        return new Promise(resolve => {
            this.poolContractInst.poolSummary().call().then(res => {
                resolve({
                    available: res[0].toString(),
                    interest: res[1].toString(),
                    totalInterest: res[2].toString(),
                })
            })
        })
    },
    getPoolGetAddrC2E(from) {
        return new Promise(resolve => {
            this.poolContractInst.getAddrC2E(from).call().then(res => {
                resolve(format.hex(res))
            })
        })
    },
    getUserSummary(from) {
        return new Promise(resolve => {
            this.poolContractInst.userSummary(from).call().then(res => {
                resolve({
                    votes: res[0].toString(),
                    available: res[1].toString(),
                    locked: res[2].toString(),
                    unlocked: res[3].toString(),
                    claimedInterest: res[4].toString(),
                    currentInterest: res[5].toString(),
                })
            })
        })
    },
    bindAddrC2E(from, eAddr, eInviter) {
        return new Promise(resolve => {
            this.poolContractInst.bindAddrC2E(format.hexBuffer(eAddr), format.hexBuffer(eInviter)).sendTransaction({
                from: from
            }).executed().then(res => {
                resolve(res)
            });
        })
    },
    increaseStake(from, votePower) {
        return new Promise(resolve => {
            this.poolContractInst.increaseStake(votePower).sendTransaction({from: from, value: Drip.fromCFX(votePower * 1000)}).executed().then(res => {
                resolve(res)
            })
        })
    }
}
